﻿using DongFangGuoKai.WCSPlatform.WebApi.ExternalSystem.AGVCommon;
using DongFangGuoKai.WCSPlatform.WebApi.ExternalSystem.WMSConmmon;
using DongFangGuoKai.WCSPlatform.WebApi.Filter;
using DongFangGuoKai.WCSPlatform.WebApi.HostService;
using DongFangGuoKai.WCSPlatform.WebApi.Utils;
using DongFangGuoKai.WMSPlatform.Commn.HttpModule;
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using MiniExcelLibs;
using NLog.Extensions.Logging;
using RestSharp;
using S7.Net;
using SqlSugar;

namespace DongFangGuoKai.WCSPlatform.WebApi.Extensions
{
    public static class WebApplicationBuilderExtension
    {
        public static Microsoft.Extensions.Configuration.IConfiguration LoadConfiguration()
        {
            // 读取配置文件
            var configuration = new ConfigurationBuilder()
                 .Add(new JsonConfigurationSource { Path = @"appsettings.json", ReloadOnChange = true })
                 .Build();
            return configuration;
        }
        /// <summary>
        /// 初始化过滤器
        /// </summary>
        /// <param name="builder"></param>
        public static void InitControllerFiter(this WebApplicationBuilder builder)
        {
            builder.Services.AddControllers(options =>
            {
                options.Filters.Add<GlobalExceptionHandler>();
                options.Filters.Add<GlobalActionFilter>();//Action过滤器
            });
        }
        /// <summary>
        /// 初始化plc实例
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitPlc(this WebApplicationBuilder builder)
        {
            //var configuration = builder.Configuration;
            var configuration = LoadConfiguration();

            string plcIp = configuration["plcIp"];
            string plcRack = configuration["plcRack"];
            string plcSlot = configuration["plcSlot"];
            string plcCpuType = configuration["plcCpuType"];
            if (string.IsNullOrEmpty(plcIp) || string.IsNullOrEmpty(plcRack) || string.IsNullOrEmpty(plcSlot))
                throw new Exception("plc配置信息不完整");

            if (!short.TryParse(plcRack, out short rack) || !short.TryParse(plcSlot, out var slot))
                throw new Exception("plc插槽号或者机架号配置信息的格式有误");

            CpuType cpuTypeEnum;
            if (plcCpuType == "1500") cpuTypeEnum = CpuType.S71500;
            else if (plcCpuType == "1200") cpuTypeEnum = CpuType.S71200;
            else throw new Exception("plc型号只能为1200或1500");

            //注入单例模式plc实例
            builder.Services.AddSingleton(provider =>
            {
                var plc = new Plc(cpuTypeEnum, plcIp, rack, slot);
                //var logger = provider.GetService<ILogger<Plc>>();
                //try
                //{
                //    plc.Open();
                //    if (plc.IsConnected) logger.LogInformation("WCS程序启动");
                //    else logger.LogError("WCS程序启动失败");
                //}
                //catch (Exception ex)
                //{
                //    logger.LogError("WCS程序启动失败:"+ex.Message);
                //}

                return plc;
            });

            //builder.Services.BuildServiceProvider().GetRequiredService<Plc>().Open();
        }

        /// <summary>
        /// 初始化plc心跳类
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitPlcHeartbeatTool(this WebApplicationBuilder builder)
        {
            var configuration = LoadConfiguration();

            var heartbeatInterval = configuration.GetValue<int?>("heartbeatInterval");//判断配置内容是否为int类型

            if (!heartbeatInterval.HasValue)
            {
                throw new Exception("heartbeatInterval 配置项必须为 int 类型且不能为空");
            }

            // 注入单例模式 PlcHeartbeatTool 实例
            builder.Services.AddSingleton(provider =>
            {
                var plc = provider.GetService<Plc>(); // 从依赖注入容器中获取 Plc 类型
                if (plc == null) throw new Exception("plc类型还未实例化");

                var logger = provider.GetService<ILogger<PlcHeartbeatTool>>(); // 从依赖注入容器中获取 Plc 类型
                if (logger == null) throw new Exception("logger类型还未实例化");

                var plcDBAddress = provider.GetService<PlcDBAddress>(); // 从依赖注入容器中获取 PlcDBAddress 类型
                if (plcDBAddress == null) throw new Exception("plcDBAddress类型还未实例化");

                var plcHeartbeatTool = new PlcHeartbeatTool(plc, heartbeatInterval.Value, plcDBAddress, logger);

                return plcHeartbeatTool;
            });

        }

        /// <summary>
        /// 初始化CtmHttpClient
        /// </summary>
        /// <param name="builder"></param>
        public static void InitCtmHttpClient(this WebApplicationBuilder builder)
        {
            builder.Services.AddSingleton(provider =>
            {
                //"http://IP:PORT"
                RestClient client = new RestClient();
                client.AddDefaultHeader("Content-Type", "application/json; charset=utf-8");
                return client;

            });

            builder.Services.AddSingleton<ICtmHttpClient, CtmHttpClient>();

        }

        /// <summary>
        /// 初始化AGVHttpTool类
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitAGVHttpTool(this WebApplicationBuilder builder)
        {
            var configuration = LoadConfiguration();

            //单例
            builder.Services.AddSingleton(provider =>
            {
                string agvBaseUrl = configuration["agvBaseUrl"];
                if (string.IsNullOrEmpty(agvBaseUrl))
                    throw new Exception("没有配置agvBaseUrl");

                var httpClient = provider.GetService<ICtmHttpClient>(); // 从依赖注入容器中获取 ICtmHttpClient 类型
                if (httpClient == null) throw new Exception("ICtmHttpClient类型还未实例化");

                var plc = provider.GetService<Plc>(); // 从依赖注入容器中获取 ICtmHttpClient 类型
                if (plc == null) throw new Exception("plc类型还未实例化");


                var logger = provider.GetService<ILogger<AGVHttpClient>>(); // 从依赖注入容器中获取 ICtmHttpClient 类型
                if (logger == null) throw new Exception("logger类型还未实例化");

                var plcDBAddress = provider.GetService<PlcDBAddress>(); // 从依赖注入容器中获取 PlcDBAddress 类型
                if (plcDBAddress == null) throw new Exception("plcDBAddress类型还未实例化");
                return new AGVHttpClient(agvBaseUrl, plc, plcDBAddress, logger, httpClient);
            });
        }

        /// <summary>
        /// 初始化WMSHttpTool
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitWMSHttpTool(this WebApplicationBuilder builder)
        {
            var configuration = LoadConfiguration();

            //单例
            builder.Services.AddSingleton(provider =>
            {
                string wmsBaseUrl = configuration["wmsBaseUrl"];
                if (string.IsNullOrEmpty(wmsBaseUrl))
                    throw new Exception("没有配置wmsBaseUrl");

                var httpClient = provider.GetService<ICtmHttpClient>(); // 从依赖注入容器中获取 ICtmHttpClient 类型
                if (httpClient == null) throw new Exception("ICtmHttpClient类型还未实例化");

                var logger = provider.GetService<ILogger<WMSHttpClient>>();
                if (logger == null) throw new Exception("logger类型还未实例化");
                return new WMSHttpClient(wmsBaseUrl, httpClient, logger);
            });
        }

        /// <summary>
        /// 初始化NLog
        /// </summary>
        /// <param name="builder"></param>
        public static void InitNLog(this WebApplicationBuilder builder)
        {
            builder.Logging.AddNLog("Config/NLog.config");
        }

        /// <summary>
        /// 初始化swagger
        /// </summary>
        /// <param name="builder"></param>
        public static void InitSwagger(this WebApplicationBuilder builder)
        {
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen(s =>
            {
                typeof(WCSApiVersions).GetEnumNames().ToList().ForEach(version =>
                {
                    s.SwaggerDoc(version, new OpenApiInfo()
                    {
                        Title = $"WCS系统接口文档",
                        Version = version,
                        Description = $"Api版本{version}"
                    });
                });

                ////添加安全定义
                //s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                //{
                //    Description = "请输入token,格式为 Bearer xxxxxxxx（注意中间必须有空格）",
                //    Name = "Authorization",
                //    In = ParameterLocation.Header,
                //    Type = SecuritySchemeType.ApiKey,
                //    BearerFormat = "JWT",
                //    Scheme = "Bearer"
                //});
                ////添加安全要求
                //s.AddSecurityRequirement(new OpenApiSecurityRequirement {
                //    {
                //        new OpenApiSecurityScheme{
                //            Reference =new OpenApiReference{
                //                Type = ReferenceType.SecurityScheme,
                //                Id ="Bearer"
                //            }
                //        },new string[]{ }
                //    }
                //});

                //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.XML";

                // xml文档绝对路径 
                var xmlFile = Path.Combine(AppContext.BaseDirectory, "DongFangGuoKai.WCSPlatform.WebApi.xml");
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                s.IncludeXmlComments(xmlPath);
            });
        }
        /// <summary>
        /// 读取配置文件中的plc地址
        /// </summary>
        /// <param name="builder"></param>
        public static void InitReadPlcDBAddressConfig(this WebApplicationBuilder builder)
        {
            // 读取配置文件
            var configuration = new ConfigurationBuilder()
                 .Add(new JsonConfigurationSource { Path = @"Config/PlcDBAddress.json", ReloadOnChange = true })
                 .Build();
            // 获取配置信息
            builder.Services.AddSingleton(provider => configuration.Get<PlcDBAddress>());
        }
        /// <summary>
        /// 初始化PlcTaskManager
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitPlcTaskManager(this WebApplicationBuilder builder)
        {
            builder.Services.AddSingleton(provider => 
            {
                var wmsHttpClient = provider.GetService<WMSHttpClient>(); // 从依赖注入容器中获取 ICtmHttpClient 类型
                if (wmsHttpClient == null) throw new Exception("wmsHttpClient类型还未实例化");

                var plc = provider.GetService<Plc>(); 
                if (plc == null) throw new Exception("plc类型还未实例化");


                var logger = provider.GetService<ILogger<PlcTaskManager>>(); 
                if (logger == null) throw new Exception("logger类型还未实例化");

                var plcDBAddress = provider.GetService<PlcDBAddress>(); // 从依赖注入容器中获取 PlcDBAddress 类型
                if (plcDBAddress == null) throw new Exception("plcDBAddress类型还未实例化");

                return new PlcTaskManager(plc, plcDBAddress, wmsHttpClient, logger);
            });
        }
        /// <summary>
        /// 后台任务
        /// </summary>
        /// <param name="builder"></param>
        public static void InitHostService(this WebApplicationBuilder builder)
        {
            builder.Services.AddHostedService<InitPlcHosetService>();
            builder.Services.AddHostedService<OutWhouseHostService>();
            //builder.Services.AddHostedService<InWhouseHostService>();
        }
        /// <summary>
        /// InitSqlSugar
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        public static void InitSqlSugar(this WebApplicationBuilder builder)
        {
            builder.Services.AddScoped<ISqlSugarClient>(provider =>
            {
                var connectionString = builder.Configuration.GetConnectionString("SqlLite");//从appsettings.json中读取连接字符串
                if (string.IsNullOrEmpty(connectionString)) { throw new Exception("SqlLite连接字符串没有配置"); }
                return new SqlSugarClient(new ConnectionConfig()//初始化sqlSaugarClient
                {
                    ConnectionString = connectionString,//连接字符串
                    DbType = DbType.Sqlite,//数据块类型 枚举
                    IsAutoCloseConnection = true,//执行完对数据库的操作后 是否自动关闭数据库连接
                });

            });
        }

    }
    public enum WCSApiVersions
    {
        V1,
        V2
    }
}
